package com.ruoyi.exam.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.google.common.base.Joiner;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.exam.domain.*;
import com.ruoyi.exam.domain.req.ExamPaperReq;
import com.ruoyi.exam.domain.vo.AnswerSheetVO;
import com.ruoyi.exam.domain.vo.ExamGeneratingPaperVO;
import com.ruoyi.exam.domain.vo.QuestionAndResultVO;
import com.ruoyi.exam.enums.ExamStatus;
import com.ruoyi.exam.enums.QuestionStatus;
import com.ruoyi.exam.enums.QuestionType;
import com.ruoyi.exam.mapper.*;
import com.ruoyi.exam.utils.LetterUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.exam.service.IExamPaperService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 试卷Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-10
 */
@Service
public class ExamPaperServiceImpl implements IExamPaperService 
{


    @Autowired
    private ExamPaperMapper examPaperMapper;

    @Autowired
    private ExamineMapper examineMapper;

    @Autowired
    private TestQuestionsMapper testQuestionsMapper;

    @Autowired
    private QuestionResultMapper questionResultMapper;
    @Autowired
    private PaperDetailQuestionMapper paperDetailQuestionMapper;
    @Autowired
    private PaperDetailQuestionResultMapper paperDetailQuestionResultMapper;

    /**
     * 查询试卷
     * 
     * @param id 试卷主键
     * @return 试卷
     */
    @Override
    public ExamPaper selectExamPaperById(Long id)
    {
        return examPaperMapper.selectExamPaperById(id);
    }

    /**
     * 查询试卷列表
     * 
     * @param examPaper 试卷
     * @return 试卷
     */
    @Override
    public List<ExamPaper> selectExamPaperList(ExamPaperReq examPaper)
    {
        return examineMapper.selectExamPaperList(examPaper);
    }

    @Override
    public List<ExamPaper> selectExamPaperList(ExamPaper examPaper) {
        return examPaperMapper.selectExamPaperList(examPaper);
    }

    /**
     * 新增试卷
     * 
     * @param examPaper 试卷
     * @return 结果
     */
    @Override
    public int insertExamPaper(ExamPaper examPaper)
    {
        examPaper.setCreateTime(DateUtils.getNowDate());
        return examPaperMapper.insertExamPaper(examPaper);
    }

    /**
     * 修改试卷
     * 
     * @param examPaper 试卷
     * @return 结果
     */
    @Override
    public int updateExamPaper(ExamPaper examPaper)
    {
        examPaper.setUpdateTime(DateUtils.getNowDate());
        return examPaperMapper.updateExamPaper(examPaper);
    }

    /**
     * 批量删除试卷
     * 
     * @param ids 需要删除的试卷主键
     * @return 结果
     */
    @Override
    public int deleteExamPaperByIds(Long[] ids)
    {
        return examPaperMapper.deleteExamPaperByIds(ids);
    }

    /**
     * 删除试卷信息
     * 
     * @param id 试卷主键
     * @return 结果
     */
    @Override
    public int deleteExamPaperById(Long id)
    {
        return examPaperMapper.deleteExamPaperById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult startExam(Long examId) {
        //1.校验考试是否有效
        AjaxResult ajaxResult =  checkExam(QuestionStatus.START_EXAM.getCode(),examId);
        if(!ajaxResult.isSuccess()) {
           return ajaxResult;
        }
        //2.生成试卷
        String examGeneratingPaper = String.valueOf(ajaxResult.get(AjaxResult.MSG_TAG));
        JSONArray examGeneratingPaperJson = JSONUtil.parseArray(examGeneratingPaper);
        List<ExamGeneratingPaperVO> examGeneratingPaperVOS = JSONUtil.toList(examGeneratingPaperJson, ExamGeneratingPaperVO.class);

        ArrayList<Long> excludesByQuestionId = new ArrayList<>();

        List<QuestionAndResultVO> questionAndResultVOList = new ArrayList<>();


        for (ExamGeneratingPaperVO examGeneratingPaperVO : examGeneratingPaperVOS) {
            if (examGeneratingPaperVO.getSingleChoiceSelectCount() > 0) {
                Long questionBlankId = examGeneratingPaperVO.getQuestionBlankId();
                int singleChoiceScore = examGeneratingPaperVO.getSingleChoiceScore();
                int singleChoiceSelectCount = examGeneratingPaperVO.getSingleChoiceSelectCount();
                String join = Joiner.on(",").join(excludesByQuestionId);
                List<QuestionAndResultVO> singleChoiceQuestions = testQuestionsMapper.randomSelectQuestion(questionBlankId, QuestionType.SINGLE_CHOICE.getCode(), singleChoiceSelectCount, join);
                if(!CollectionUtil.isEmpty(singleChoiceQuestions)){
                    singleChoiceQuestions.forEach(questionAndResultVO -> {
                        questionAndResultVO.getPaperDetailQuestion().setTopicScore(singleChoiceScore);
                    });
                    questionAndResultVOList.addAll(singleChoiceQuestions);
                    List<Long> questionIds = singleChoiceQuestions.stream().map(QuestionAndResultVO::getPaperDetailQuestion).map(PaperDetailQuestion::getId).collect(Collectors.toList());
                    excludesByQuestionId.addAll(questionIds);
                }

            }

            if (examGeneratingPaperVO.getMultipleChoiceSelectCount() > 0) {
                Long questionBlankId = examGeneratingPaperVO.getQuestionBlankId();
                int multipleChoiceSelectCount = examGeneratingPaperVO.getMultipleChoiceSelectCount();
                int multipleChoiceScore = examGeneratingPaperVO.getMultipleChoiceScore();
                String join = Joiner.on(",").join(excludesByQuestionId);
                List<QuestionAndResultVO> multipleChoiceQuestions = testQuestionsMapper.randomSelectQuestion(questionBlankId, QuestionType.MULTIPLE_CHOICE.getCode(), multipleChoiceSelectCount, join);
                if(!CollectionUtil.isEmpty(multipleChoiceQuestions)){
                    multipleChoiceQuestions.forEach(questionAndResultVO -> {
                        questionAndResultVO.getPaperDetailQuestion().setTopicScore(multipleChoiceScore);
                    });
                    questionAndResultVOList.addAll(multipleChoiceQuestions);
                    List<Long> questionIds = multipleChoiceQuestions.stream().map(QuestionAndResultVO::getPaperDetailQuestion).map(PaperDetailQuestion::getId).collect(Collectors.toList());
                    excludesByQuestionId.addAll(questionIds);
                }


            }

            if (examGeneratingPaperVO.getTrueorfalseQuestionsSelectCount() > 0) {
                Long questionBlankId = examGeneratingPaperVO.getQuestionBlankId();
                int judgementSelectCount = examGeneratingPaperVO.getTrueorfalseQuestionsSelectCount();
                int singleChoiceScore = examGeneratingPaperVO.getSingleChoiceScore();
                String join = Joiner.on(",").join(excludesByQuestionId);
                List<QuestionAndResultVO> judgementQuestions = testQuestionsMapper.randomSelectQuestion(questionBlankId, QuestionType.TRUEORFALSE_CHOICE.getCode(), judgementSelectCount, join);
                if(!CollectionUtil.isEmpty(judgementQuestions)){
                    judgementQuestions.forEach(questionAndResultVO -> {
                        questionAndResultVO.getPaperDetailQuestion().setTopicScore(singleChoiceScore);
                    });
                    questionAndResultVOList.addAll(judgementQuestions);
                    List<Long> questionIds = judgementQuestions.stream().map(QuestionAndResultVO::getPaperDetailQuestion).map(PaperDetailQuestion::getId).collect(Collectors.toList());
                    excludesByQuestionId.addAll(questionIds);
                }


            }
        }
        //保存试卷表
        Long paperId = saveExampaper(examId);
//        List<PaperDetailQuestion> paperDetailQuestionList = new ArrayList<>();
//        List<PaperDetailQuestionResult> paperDetailQuestionResultList = new ArrayList<>();
        //保存试卷的题目和答案
        saveQuestionAndResult(questionAndResultVOList,paperId);

        return AjaxResult.success(paperId);

    }

    @Override
    public AjaxResult getAnswerSheet(Long paperId) {
        ExamPaper examPaper = examPaperMapper.selectExamPaperById(paperId);
        AjaxResult ajaxResult = checkExam(QuestionStatus.GET_ANSWER_SHEET.getCode(),examPaper.getExamId());
        if(!ajaxResult.isSuccess()) {
            return ajaxResult;
        }
        Long userid = SecurityUtils.getLoginUser().getUserid();
        List<QuestionAndResultVO> questionAndResultVOList = paperDetailQuestionMapper.selectQuestionAndResult(paperId,userid);
       if(CollectionUtil.isEmpty(questionAndResultVOList)) {
           return AjaxResult.error("试卷不存在题目");
       }

        AnswerSheetVO answerSheetVO = new AnswerSheetVO();
        List<QuestionAndResultVO> singleChoiceQuestions = questionAndResultVOList.stream().filter(questionAndResultVO -> questionAndResultVO.getPaperDetailQuestion().getTopicType().intValue() == QuestionType.SINGLE_CHOICE.getCode()).collect(Collectors.toList());
        answerSheetVO.setSingleChoiceQuestions(singleChoiceQuestions);
        buildQuestionResultLetter(singleChoiceQuestions);

        List<QuestionAndResultVO> multipleChoiceQuestions = questionAndResultVOList.stream().filter(questionAndResultVO -> questionAndResultVO.getPaperDetailQuestion().getTopicType().intValue() == QuestionType.MULTIPLE_CHOICE.getCode()).collect(Collectors.toList());
        answerSheetVO.setMultipleChoiceQuestions(multipleChoiceQuestions);

        buildQuestionResultLetter(multipleChoiceQuestions);

        List<QuestionAndResultVO> judgeQuestions = questionAndResultVOList.stream().filter(questionAndResultVO -> questionAndResultVO.getPaperDetailQuestion().getTopicType().intValue() == QuestionType.TRUEORFALSE_CHOICE.getCode()).collect(Collectors.toList());
        buildQuestionResultLetter(judgeQuestions);

        answerSheetVO.setJudgeQuestions(judgeQuestions);


        return AjaxResult.success(answerSheetVO);
    }

    private void buildQuestionResultLetter(List<QuestionAndResultVO> singleChoiceQuestions) {
        for (QuestionAndResultVO singleChoiceQuestion : singleChoiceQuestions) {
            List<PaperDetailQuestionResult> paperDetailQuestionResultList = singleChoiceQuestion.getPaperDetailQuestionResultList();
            for (int i = 0; i < paperDetailQuestionResultList.size(); i++) {
                String resultContent = paperDetailQuestionResultList.get(i).getResultContent();
                String letter = LetterUtil.getLetter(i);
                paperDetailQuestionResultList.get(i).setResultContent(letter+"."+resultContent);
            }
        }
    }

    private void saveQuestionAndResult(List<QuestionAndResultVO> questionAndResultVOList, Long paperId) {
        for (QuestionAndResultVO questionAndResultVO : questionAndResultVOList) {
            PaperDetailQuestion paperDetailQuestion = questionAndResultVO.getPaperDetailQuestion();
            paperDetailQuestion.setPaperId(paperId);
            paperDetailQuestionMapper.insertPaperDetailQuestion(paperDetailQuestion);
            List<PaperDetailQuestionResult> paperDetailQuestionResultList1 = questionAndResultVO.getPaperDetailQuestionResultList();
            paperDetailQuestionResultList1.forEach(paperDetailQuestionResult -> {
                paperDetailQuestionResult.setDetailQuestionId(paperDetailQuestion.getId());
            });
            paperDetailQuestionResultMapper.insertBatch(paperDetailQuestionResultList1);
        }
    }

    private Long saveExampaper(Long examId) {
        ExamPaper examPaper = new ExamPaper();
        examPaper.setExamId(examId);
        examPaper.setUserId(SecurityUtils.getLoginUser().getUserid());
        examPaper.setUserName(SecurityUtils.getLoginUser().getUsername());
        examPaperMapper.insertExamPaper(examPaper);
        return examPaper.getId();
    }

    public AjaxResult checkExam(Integer code, Long examId) {

        Examine examine = examineMapper.selectExamineById(examId);
        if(examine == null) {
            return AjaxResult.error("试卷不存在");
        }
        if(examine.getExamStatus().intValue() != ExamStatus.ENABLE.getCode()) {
            return AjaxResult.error("考试是禁用状态");
        }
        Date examStartTime = examine.getExamStartTime();
        Date examStopTime = examine.getExamStopTime();
        if(examStartTime != null && examStopTime != null) {
            Date now = new Date();
            if(now.before(examStartTime)) {
                return AjaxResult.error("考试还未开始");
            }
            if(now.after(examStopTime)) {
                return AjaxResult.error("考试已经结束");
            }
        }
        Long userId = SecurityUtils.getLoginUser().getUserid();
        //判断该用户所属部门是否能参加该考试
        if(examine.getExamType().intValue() == 1){
            Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();//22
            String deptIds = examine.getDeptIds();//23,24,25
            deptIds.contains(String.valueOf(deptId));
            String[] deptIdArr = deptIds.split(",");
            boolean contains = Arrays.stream(deptIdArr).anyMatch(deptIdItem -> deptIdItem.equals(String.valueOf(deptId)));
            if(!contains){
                return AjaxResult.error("您所属部门不能参加该考试");
            }
        }
      

        if(code == QuestionStatus.START_EXAM.getCode().intValue()){
            //判断用户是否有进行中的考试
            int userExamCount =  examPaperMapper.selectExamPaperByExamId(examId,userId);
            if(userExamCount > 0) {
                return AjaxResult.error("您有考试正在进行中");
            }
        }

        String examGeneratingPaper = examine.getExamGeneratingPaper();
        if(StringUtils.isEmpty(examGeneratingPaper)){
            return AjaxResult.error("试卷为空，请练习考务");
        }
        return AjaxResult.success(examGeneratingPaper);

    }

    public static void main(String[] args) {
//        ArrayList<Long> excludesByQuestionId = new ArrayList<>();
//        String join = Joiner.on(",").join(excludesByQuestionId);
//        System.out.println("println-->"+join);
        Long deptId = 2L;
        String deptIds = "23,24,25";//
//        boolean contains = deptIds.contains(String.valueOf(deptId));
        String[] split = deptIds.split(",");
        boolean contains = Arrays.stream(split).anyMatch(deptIdItem -> deptIdItem.equals(String.valueOf(deptId)));

//        boolean contains = false;
//        for (String s : split) {
//            if(s.equals(String.valueOf(deptId))){
//                contains = true;
//                break;
//            }
//        }
        System.out.println("contains-->"+contains);

    }

}
